{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Pandas 如何根据需要创建简单模型"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "大家好，今天这一期我想和大家分享有关于pandas创建模型的部分，首先让我们来看一个比较常见的场景：\n",
    "\n",
    ">**你每天需要打开N个excel进行相同的操作，各种眼花缭乱的VBA函数后老眼昏花。。。。\n",
    "\n",
    "这种情况下，最好的解决办法是先仔细想想业务需求是什么，根据实际情况可以用pandas搭建一个小型模型，一旦搭建完毕，你每天上班时就可以愉快地运行Python脚本，转身去喝杯咖啡，几分钟后心满意足地回来，发现所有的繁琐操作已经搞定了，生活是这么美好、、、\n",
    "\n",
    "\n",
    "闲话少说，让我今天抛砖引玉，为大家简单介绍一个我使用比较多的小模型：检验数据一致性（新老数据增加和减少的数量一致），今天的文章主要分为5部分\n",
    "\n",
    "1. 制作假数据\n",
    "2. 明确模型的目的\n",
    "3. 开始实践\n",
    "4. 源码及GitHub地址\n",
    "\n",
    "好啦，话不多说，让我们一个个看吧"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1. 制作假数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'F:\\\\Python教程\\\\segmentfault\\\\pandas_share\\\\Pandas之旅_05 如何构建基础模型'"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#这两行仅仅是切换路径，方便我上传Github，大家不用理会\n",
    "os.chdir(\"F:\\\\Python教程\\\\segmentfault\\\\pandas_share\\\\Pandas之旅_05 如何构建基础模型\")\n",
    "os.getcwd()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "首先让我们一起制作一些假数据，我这里接下来生成一些有关订单的假数据，当然，到了文章的最后可能你会发现我们的模型并不是完美适用于这个类型，你会在生活中根据自己需要来调整，但是至少基础的思路已经有啦！"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "先建立一个fake_product的字典，keys是产品，value是单价，这里我们用一个在网上随便找到的商品名称的csv数据集,它只有一列ProductNames"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'Using pandas,0.23.0'"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import numpy as np\n",
    "import pandas as pd\n",
    "f\"Using {pd.__name__},{pd.__version__}\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Product_Names</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>TrailChef Deluxe Cook Set</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>TrailChef Double Flame</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>Star Dome</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>Star Gazer 2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>Hibernator Lite</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>Hibernator Extreme</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>Hibernator Camp Cot</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>Firefly Lite</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>Firefly Extreme</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>EverGlow Single</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "               Product_Names\n",
       "0  TrailChef Deluxe Cook Set\n",
       "1     TrailChef Double Flame\n",
       "2                  Star Dome\n",
       "3               Star Gazer 2\n",
       "4            Hibernator Lite\n",
       "5         Hibernator Extreme\n",
       "6        Hibernator Camp Cot\n",
       "7               Firefly Lite\n",
       "8            Firefly Extreme\n",
       "9            EverGlow Single"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "fake_df = pd.read_csv(\"product_names.csv\")\n",
    "fake_df.head(10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "fake_df['Product_Names'].is_unique"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这里我们可以看到，数据集主要包括的就是一些产品的名字，而且没有重复值，我们现在把他们导出至一个字典，并随机给每个产品任意的价格(在20至100之间),因为这里我们要随机生成一些假数据，所以让我们引用random这个包"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "import random"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'TrailChef Deluxe Cook Set': 62,\n",
       " 'TrailChef Double Flame': 78,\n",
       " 'Star Dome': 58,\n",
       " 'Star Gazer 2': 73,\n",
       " 'Hibernator Lite': 56,\n",
       " 'Hibernator Extreme': 99,\n",
       " 'Hibernator Camp Cot': 33,\n",
       " 'Firefly Lite': 27,\n",
       " 'Firefly Extreme': 30,\n",
       " 'EverGlow Single': 44,\n",
       " 'EverGlow Butane': 33,\n",
       " 'Husky Rope 50': 59,\n",
       " 'Husky Rope 60': 81,\n",
       " 'Husky Rope 100': 71,\n",
       " 'Husky Rope 200': 81,\n",
       " 'Granite Climbing Helmet': 86,\n",
       " 'Husky Harness': 76,\n",
       " 'Husky Harness Extreme': 73,\n",
       " 'Granite Signal Mirror': 67,\n",
       " 'Granite Carabiner': 63,\n",
       " 'Granite Belay': 49,\n",
       " 'Granite Pulley': 48,\n",
       " 'Firefly Climbing Lamp': 47,\n",
       " 'Firefly Charger': 60,\n",
       " 'Firefly Rechargeable Battery': 52,\n",
       " 'Granite Chalk Bag': 22,\n",
       " 'Granite Ice': 71,\n",
       " 'Granite Hammer': 50,\n",
       " 'Granite Shovel': 41,\n",
       " 'Granite Grip': 74,\n",
       " 'Granite Axe': 68,\n",
       " 'Granite Extreme': 74,\n",
       " 'Mountain Man Extreme': 87,\n",
       " 'Polar Sun': 82,\n",
       " 'Polar Ice': 47,\n",
       " 'Edge Extreme': 53,\n",
       " 'Bear Survival Edge': 81,\n",
       " 'Glacier GPS Extreme': 48,\n",
       " 'BugShield Extreme': 87,\n",
       " 'Sun Shelter Stick': 42,\n",
       " 'Compact Relief Kit': 46,\n",
       " 'Aloe Relief': 24,\n",
       " 'Infinity': 73,\n",
       " 'TX': 43,\n",
       " 'Legend': 100,\n",
       " 'Kodiak': 44,\n",
       " 'Capri': 31,\n",
       " 'Cat Eye': 62,\n",
       " 'Dante': 71,\n",
       " 'Fairway': 77,\n",
       " 'Inferno': 59,\n",
       " 'Maximus': 38,\n",
       " 'Trendi': 35,\n",
       " 'Zone': 87,\n",
       " 'Max Gizmo': 67,\n",
       " 'Pocket Gizmo': 73,\n",
       " 'Ranger Vision': 73,\n",
       " 'Trail Master': 96,\n",
       " 'Hailstorm Steel Irons': 79,\n",
       " 'Hailstorm Titanium Irons': 31,\n",
       " 'Lady Hailstorm Steel Irons': 91,\n",
       " 'Lady Hailstorm Titanium Irons': 99,\n",
       " 'Hailstorm Titanium Woods Set': 74,\n",
       " 'Hailstorm Steel Woods Set': 30,\n",
       " 'Lady Hailstorm Titanium Woods Set': 99,\n",
       " 'Lady Hailstorm Steel Woods Set': 84,\n",
       " 'Course Pro Putter': 64,\n",
       " 'Blue Steel Putter': 26,\n",
       " 'Blue Steel Max Putter': 96,\n",
       " 'Course Pro Golf and Tee Set': 90,\n",
       " 'Course Pro Umbrella': 20,\n",
       " 'Course Pro Golf Bag': 66,\n",
       " 'Course Pro Gloves': 61,\n",
       " 'TrailChef Canteen': 60,\n",
       " 'TrailChef Kitchen Kit': 53,\n",
       " 'TrailChef Cup': 88,\n",
       " 'TrailChef Cook Set': 27,\n",
       " 'TrailChef Single Flame': 45,\n",
       " 'TrailChef Kettle': 70,\n",
       " 'TrailChef Utensils': 88,\n",
       " 'Star Gazer 6': 42,\n",
       " 'Star Peg': 28,\n",
       " 'Hibernator': 47,\n",
       " 'Hibernator Self - Inflating Mat': 66,\n",
       " 'Hibernator Pad': 89,\n",
       " 'Hibernator Pillow': 84,\n",
       " 'Canyon Mule Climber Backpack': 82,\n",
       " 'Canyon Mule Weekender Backpack': 92,\n",
       " 'Canyon Mule Journey Backpack': 82,\n",
       " 'Canyon Mule Cooler': 23,\n",
       " 'Canyon Mule Carryall': 56,\n",
       " 'Firefly Mapreader': 77,\n",
       " 'Firefly 2': 76,\n",
       " 'Firefly 4': 75,\n",
       " 'Firefly Multi-light': 91,\n",
       " 'EverGlow Double': 34,\n",
       " 'EverGlow Lamp': 28,\n",
       " 'Mountain Man Analog': 39,\n",
       " 'Mountain Man Digital': 85,\n",
       " 'Mountain Man Deluxe': 84,\n",
       " 'Mountain Man Combination': 40,\n",
       " 'Venue': 56,\n",
       " 'Lux': 44,\n",
       " 'Polar Sports': 20,\n",
       " 'Polar Wave': 62,\n",
       " 'Bella': 45,\n",
       " 'Hawk Eye': 42,\n",
       " 'Seeker 35': 81,\n",
       " 'Seeker 50': 90,\n",
       " 'Opera Vision': 98,\n",
       " 'Glacier Basic': 63,\n",
       " 'Glacier GPS': 66,\n",
       " 'Trail Scout': 32,\n",
       " 'BugShield Spray': 34,\n",
       " 'BugShield Lotion Lite': 90,\n",
       " 'BugShield Lotion': 84,\n",
       " 'Sun Blocker': 88,\n",
       " 'Sun Shelter 15': 45,\n",
       " 'Sun Shelter 30': 100,\n",
       " 'Sun Shield': 62,\n",
       " 'Deluxe Family Relief Kit': 43,\n",
       " 'Calamine Relief': 82,\n",
       " 'Insect Bite Relief': 72,\n",
       " 'Star Lite': 32,\n",
       " 'Star Gazer 3': 95,\n",
       " 'Single Edge': 87,\n",
       " 'Double Edge': 20,\n",
       " 'Bear Edge': 80,\n",
       " 'Glacier Deluxe': 82,\n",
       " 'BugShield Natural': 83,\n",
       " 'TrailChef Water Bag': 99,\n",
       " 'Canyon Mule Extreme Backpack': 58,\n",
       " 'EverGlow Kerosene': 78,\n",
       " 'Sam': 67,\n",
       " 'Polar Extreme': 34,\n",
       " 'Seeker Extreme': 43,\n",
       " 'Seeker Mini': 26,\n",
       " 'Flicker Lantern': 44,\n",
       " 'Trail Star': 47,\n",
       " 'Zodiak': 31,\n",
       " 'Sky Pilot': 58,\n",
       " 'Retro': 99,\n",
       " 'Astro Pilot': 99,\n",
       " 'Auto Pilot': 20}"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "fake_product = { k:random.randint(20,100) for k in fake_df['Product_Names']}\n",
    "fake_product"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "144"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(fake_product)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    " 这里我们看到生成了一个有144个item组成，key为产品名称，value及单价的fake_product字典，接下来为了省事，\n",
    "我简单地创建了一个方法get_fake_data可以让我们最终得到一个填充好的假数据集合，返回的也是字典"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "def get_fake_data(id_range_start,id_range_end,random_quantity_range=50):\n",
    "#     Id=[\"A00\"+str(i) for i in range(0,id_range)]\n",
    "    Id=[]\n",
    "    Quantity = []\n",
    "    Product_name=[]\n",
    "    Unit_price=[]\n",
    "    Total_price=[]\n",
    "\n",
    "    for i in range(id_range_start,id_range_end):\n",
    "        random_quantity = random.randint(1,random_quantity_range)\n",
    "        name, price = random.choice(list(fake_product.items()))\n",
    "\n",
    "        Id.append(\"A00\"+str(i))\n",
    "        Quantity.append(random_quantity)\n",
    "        Product_name.append(name)\n",
    "        Unit_price.append(price)\n",
    "        Total_price.append(price*random_quantity)\n",
    "   \n",
    "    result = {\n",
    "    'Product_ID':Id,\n",
    "    'Product_Name':Product_name,\n",
    "    'Quantity':Quantity,\n",
    "    'Unit_price':Unit_price,\n",
    "    'Total_price':Total_price\n",
    "}\n",
    "    \n",
    "    return result\n",
    "\n",
    "# total = [quantity[i]* v for i,v in enumerate(unit_price)]    也可以最后用推导式来求total，皮一下\n",
    "# total_price=[q*p for q in quantity for p in unit_price]\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "首先，这个方法不够简洁，大家可以优化一下，但是今天的重点在于小模型，让我们着重看一下最后返回的dict，它包含如下几列：\n",
    " - Product_ID：订单号，按照顺序递增生成\n",
    " - Product_Name：产品名称，随机生成\n",
    " - Quantity：随机生成在1~random_quantity_range之间的每个订单的产品订购量\n",
    " - Unit_price:产品价格\n",
    " - Total_price：总价\n",
    "  \n",
    "每组数据长度均为 id_range_end - id_range_start，现在让我们生成两组假数据："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "fake_data= get_fake_data(1,len(fake_product)+1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这里我们可以看到我们生成了一组假数据，Id从A001 ~ A00145"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "让我们简单看看假数据的keys和每组数据的长度："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "dict_keys(['Product_ID', 'Product_Name', 'Quantity', 'Unit_price', 'Total_price'])"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "fake_data.keys()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "144\n",
      "144\n",
      "144\n",
      "144\n",
      "144\n"
     ]
    }
   ],
   "source": [
    "for v in fake_data.values():\n",
    "    print(len(v))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "可以发现每组key对应的list长度都是144"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2. 明确模型的目的"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "我们可以利用pandas自带的from_dict方法把dict转化为Dataframe，这里我们分别用刚刚生成的fake_data来模拟1月的库存和2月的库存情况，我们可以把fake_data分成两组，A001-A00140一组，A008-A00144一组，这样就完美的模拟了实际情况。\n",
    "\n",
    "因为大多数的商品名称不会改变（8~140的部分），但是从一月到二月，因为各种原因我们减少了7个商品种类的库存（1-7），又增加了4个种类的库存（141-144），我们这里验证一致性的公式就是：\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> 新增的 + 一月数据总量 = 减少的 + 二月数据总量"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3. 开始实践"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "现在让我们来实现这个小模型，首先生成stock_jan，stock_fev两个dataframe"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Product_ID</th>\n",
       "      <th>Product_Name</th>\n",
       "      <th>Quantity</th>\n",
       "      <th>Unit_price</th>\n",
       "      <th>Total_price</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>A001</td>\n",
       "      <td>Course Pro Golf Bag</td>\n",
       "      <td>39</td>\n",
       "      <td>66</td>\n",
       "      <td>2574</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>A002</td>\n",
       "      <td>EverGlow Kerosene</td>\n",
       "      <td>18</td>\n",
       "      <td>78</td>\n",
       "      <td>1404</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>A003</td>\n",
       "      <td>Lux</td>\n",
       "      <td>24</td>\n",
       "      <td>44</td>\n",
       "      <td>1056</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>A004</td>\n",
       "      <td>Course Pro Putter</td>\n",
       "      <td>12</td>\n",
       "      <td>64</td>\n",
       "      <td>768</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>A005</td>\n",
       "      <td>Seeker 50</td>\n",
       "      <td>42</td>\n",
       "      <td>90</td>\n",
       "      <td>3780</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "  Product_ID         Product_Name  Quantity  Unit_price  Total_price\n",
       "0       A001  Course Pro Golf Bag        39          66         2574\n",
       "1       A002    EverGlow Kerosene        18          78         1404\n",
       "2       A003                  Lux        24          44         1056\n",
       "3       A004    Course Pro Putter        12          64          768\n",
       "4       A005            Seeker 50        42          90         3780"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "stock= pd.DataFrame.from_dict(fake_data)\n",
    "stock.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Product_Name</th>\n",
       "      <th>Quantity</th>\n",
       "      <th>Unit_price</th>\n",
       "      <th>Total_price</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Product_ID</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>A001</th>\n",
       "      <td>Course Pro Golf Bag</td>\n",
       "      <td>39</td>\n",
       "      <td>66</td>\n",
       "      <td>2574</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>A002</th>\n",
       "      <td>EverGlow Kerosene</td>\n",
       "      <td>18</td>\n",
       "      <td>78</td>\n",
       "      <td>1404</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>A003</th>\n",
       "      <td>Lux</td>\n",
       "      <td>24</td>\n",
       "      <td>44</td>\n",
       "      <td>1056</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>A004</th>\n",
       "      <td>Course Pro Putter</td>\n",
       "      <td>12</td>\n",
       "      <td>64</td>\n",
       "      <td>768</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>A005</th>\n",
       "      <td>Seeker 50</td>\n",
       "      <td>42</td>\n",
       "      <td>90</td>\n",
       "      <td>3780</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                   Product_Name  Quantity  Unit_price  Total_price\n",
       "Product_ID                                                        \n",
       "A001        Course Pro Golf Bag        39          66         2574\n",
       "A002          EverGlow Kerosene        18          78         1404\n",
       "A003                        Lux        24          44         1056\n",
       "A004          Course Pro Putter        12          64          768\n",
       "A005                  Seeker 50        42          90         3780"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "stock.set_index(stock['Product_ID'],inplace=True)\n",
    "stock.drop('Product_ID',axis=1,inplace=True)\n",
    "stock.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Product_Name</th>\n",
       "      <th>Quantity</th>\n",
       "      <th>Unit_price</th>\n",
       "      <th>Total_price</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Product_ID</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>A00136</th>\n",
       "      <td>Flicker Lantern</td>\n",
       "      <td>1</td>\n",
       "      <td>44</td>\n",
       "      <td>44</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>A00137</th>\n",
       "      <td>BugShield Spray</td>\n",
       "      <td>8</td>\n",
       "      <td>34</td>\n",
       "      <td>272</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>A00138</th>\n",
       "      <td>Glacier Basic</td>\n",
       "      <td>25</td>\n",
       "      <td>63</td>\n",
       "      <td>1575</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>A00139</th>\n",
       "      <td>Sun Blocker</td>\n",
       "      <td>23</td>\n",
       "      <td>88</td>\n",
       "      <td>2024</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>A00140</th>\n",
       "      <td>Granite Carabiner</td>\n",
       "      <td>11</td>\n",
       "      <td>63</td>\n",
       "      <td>693</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                 Product_Name  Quantity  Unit_price  Total_price\n",
       "Product_ID                                                      \n",
       "A00136        Flicker Lantern         1          44           44\n",
       "A00137        BugShield Spray         8          34          272\n",
       "A00138          Glacier Basic        25          63         1575\n",
       "A00139            Sun Blocker        23          88         2024\n",
       "A00140      Granite Carabiner        11          63          693"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 获得1月份stock数据,A001-A00140\n",
    "stock_jan=stock[:'A00140']\n",
    "stock_jan.tail()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Product_Name</th>\n",
       "      <th>Quantity</th>\n",
       "      <th>Unit_price</th>\n",
       "      <th>Total_price</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Product_ID</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>A00140</th>\n",
       "      <td>Granite Carabiner</td>\n",
       "      <td>11</td>\n",
       "      <td>63</td>\n",
       "      <td>693</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>A00141</th>\n",
       "      <td>TrailChef Utensils</td>\n",
       "      <td>24</td>\n",
       "      <td>88</td>\n",
       "      <td>2112</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>A00142</th>\n",
       "      <td>TrailChef Deluxe Cook Set</td>\n",
       "      <td>9</td>\n",
       "      <td>62</td>\n",
       "      <td>558</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>A00143</th>\n",
       "      <td>Trail Star</td>\n",
       "      <td>21</td>\n",
       "      <td>47</td>\n",
       "      <td>987</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>A00144</th>\n",
       "      <td>Ranger Vision</td>\n",
       "      <td>19</td>\n",
       "      <td>73</td>\n",
       "      <td>1387</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                         Product_Name  Quantity  Unit_price  Total_price\n",
       "Product_ID                                                              \n",
       "A00140              Granite Carabiner        11          63          693\n",
       "A00141             TrailChef Utensils        24          88         2112\n",
       "A00142      TrailChef Deluxe Cook Set         9          62          558\n",
       "A00143                     Trail Star        21          47          987\n",
       "A00144                  Ranger Vision        19          73         1387"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 获得2月份stock数据\n",
    "stock_fev=stock['A008':]\n",
    "stock_fev.tail()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "现在让我们简单停顿一下，看看这两个df：\n",
    " - stock_jan: A001 - A00140的所有数据\n",
    " - stock_fev: A008 - A00144的所有数据\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "接下来的操作很简单，用我们上篇文章提到的merge函数，这里merge的公有列为索引Product_ID，Product_Name,使用的是outer merge"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "merge_keys=['Product_ID','Product_Name'] "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Product_Name</th>\n",
       "      <th>Quantity_jan</th>\n",
       "      <th>Unit_price_jan</th>\n",
       "      <th>Total_price_jan</th>\n",
       "      <th>Quantity_fev</th>\n",
       "      <th>Unit_price_fev</th>\n",
       "      <th>Total_price_fev</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Product_ID</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>A001</th>\n",
       "      <td>Course Pro Golf Bag</td>\n",
       "      <td>39.0</td>\n",
       "      <td>66.0</td>\n",
       "      <td>2574.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>A002</th>\n",
       "      <td>EverGlow Kerosene</td>\n",
       "      <td>18.0</td>\n",
       "      <td>78.0</td>\n",
       "      <td>1404.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>A003</th>\n",
       "      <td>Lux</td>\n",
       "      <td>24.0</td>\n",
       "      <td>44.0</td>\n",
       "      <td>1056.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>A004</th>\n",
       "      <td>Course Pro Putter</td>\n",
       "      <td>12.0</td>\n",
       "      <td>64.0</td>\n",
       "      <td>768.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>A005</th>\n",
       "      <td>Seeker 50</td>\n",
       "      <td>42.0</td>\n",
       "      <td>90.0</td>\n",
       "      <td>3780.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>A006</th>\n",
       "      <td>Course Pro Golf Bag</td>\n",
       "      <td>27.0</td>\n",
       "      <td>66.0</td>\n",
       "      <td>1782.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>A007</th>\n",
       "      <td>Husky Rope 100</td>\n",
       "      <td>3.0</td>\n",
       "      <td>71.0</td>\n",
       "      <td>213.0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>A008</th>\n",
       "      <td>EverGlow Double</td>\n",
       "      <td>18.0</td>\n",
       "      <td>34.0</td>\n",
       "      <td>612.0</td>\n",
       "      <td>18.0</td>\n",
       "      <td>34.0</td>\n",
       "      <td>612.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>A009</th>\n",
       "      <td>Opera Vision</td>\n",
       "      <td>30.0</td>\n",
       "      <td>98.0</td>\n",
       "      <td>2940.0</td>\n",
       "      <td>30.0</td>\n",
       "      <td>98.0</td>\n",
       "      <td>2940.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>A0010</th>\n",
       "      <td>TX</td>\n",
       "      <td>38.0</td>\n",
       "      <td>43.0</td>\n",
       "      <td>1634.0</td>\n",
       "      <td>38.0</td>\n",
       "      <td>43.0</td>\n",
       "      <td>1634.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                   Product_Name  Quantity_jan  Unit_price_jan  \\\n",
       "Product_ID                                                      \n",
       "A001        Course Pro Golf Bag          39.0            66.0   \n",
       "A002          EverGlow Kerosene          18.0            78.0   \n",
       "A003                        Lux          24.0            44.0   \n",
       "A004          Course Pro Putter          12.0            64.0   \n",
       "A005                  Seeker 50          42.0            90.0   \n",
       "A006        Course Pro Golf Bag          27.0            66.0   \n",
       "A007             Husky Rope 100           3.0            71.0   \n",
       "A008            EverGlow Double          18.0            34.0   \n",
       "A009               Opera Vision          30.0            98.0   \n",
       "A0010                        TX          38.0            43.0   \n",
       "\n",
       "            Total_price_jan  Quantity_fev  Unit_price_fev  Total_price_fev  \n",
       "Product_ID                                                                  \n",
       "A001                 2574.0           NaN             NaN              NaN  \n",
       "A002                 1404.0           NaN             NaN              NaN  \n",
       "A003                 1056.0           NaN             NaN              NaN  \n",
       "A004                  768.0           NaN             NaN              NaN  \n",
       "A005                 3780.0           NaN             NaN              NaN  \n",
       "A006                 1782.0           NaN             NaN              NaN  \n",
       "A007                  213.0           NaN             NaN              NaN  \n",
       "A008                  612.0          18.0            34.0            612.0  \n",
       "A009                 2940.0          30.0            98.0           2940.0  \n",
       "A0010                1634.0          38.0            43.0           1634.0  "
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "check_corehence = stock_jan.merge(stock_fev,on=merge_keys,how='outer',suffixes=(\"_jan\",\"_fev\"))\n",
    "check_corehence.head(10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Product_Name</th>\n",
       "      <th>Quantity_jan</th>\n",
       "      <th>Unit_price_jan</th>\n",
       "      <th>Total_price_jan</th>\n",
       "      <th>Quantity_fev</th>\n",
       "      <th>Unit_price_fev</th>\n",
       "      <th>Total_price_fev</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Product_ID</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>A00140</th>\n",
       "      <td>Granite Carabiner</td>\n",
       "      <td>11.0</td>\n",
       "      <td>63.0</td>\n",
       "      <td>693.0</td>\n",
       "      <td>11.0</td>\n",
       "      <td>63.0</td>\n",
       "      <td>693.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>A00141</th>\n",
       "      <td>TrailChef Utensils</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>24.0</td>\n",
       "      <td>88.0</td>\n",
       "      <td>2112.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>A00142</th>\n",
       "      <td>TrailChef Deluxe Cook Set</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>9.0</td>\n",
       "      <td>62.0</td>\n",
       "      <td>558.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>A00143</th>\n",
       "      <td>Trail Star</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>21.0</td>\n",
       "      <td>47.0</td>\n",
       "      <td>987.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>A00144</th>\n",
       "      <td>Ranger Vision</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>19.0</td>\n",
       "      <td>73.0</td>\n",
       "      <td>1387.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                         Product_Name  Quantity_jan  Unit_price_jan  \\\n",
       "Product_ID                                                            \n",
       "A00140              Granite Carabiner          11.0            63.0   \n",
       "A00141             TrailChef Utensils           NaN             NaN   \n",
       "A00142      TrailChef Deluxe Cook Set           NaN             NaN   \n",
       "A00143                     Trail Star           NaN             NaN   \n",
       "A00144                  Ranger Vision           NaN             NaN   \n",
       "\n",
       "            Total_price_jan  Quantity_fev  Unit_price_fev  Total_price_fev  \n",
       "Product_ID                                                                  \n",
       "A00140                693.0          11.0            63.0            693.0  \n",
       "A00141                  NaN          24.0            88.0           2112.0  \n",
       "A00142                  NaN           9.0            62.0            558.0  \n",
       "A00143                  NaN          21.0            47.0            987.0  \n",
       "A00144                  NaN          19.0            73.0           1387.0  "
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "check_corehence.tail()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "大家可以发现前7行正是减少的商品库存，而后4行正是二月份新增的商品库存，现在让我们分别获得减少的商品库存数据和新增的商品库存数据："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "new_stock = check_corehence.loc[(check_corehence['Quantity_jan'].isnull()) & (check_corehence['Quantity_fev'].notnull())]\n",
    "num_new = new_stock.shape[0]\n",
    "num_new"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "7"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "remove_stock = check_corehence.loc[(check_corehence['Quantity_fev'].isnull()) & (check_corehence['Quantity_jan'].notnull())]\n",
    "num_remove = remove_stock.shape[0]\n",
    "num_remove"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "再让我们分别看看1月和2月的数据量："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "140"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 1月数据量\n",
    "num_stock_jan = stock_jan.shape[0]\n",
    "num_stock_jan"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "137"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 2月数据量\n",
    "num_stock_fev = stock_fev.shape[0]\n",
    "num_stock_fev"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "现在让我们套入公式："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "144"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "num_stock_jan + num_new"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "144"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "num_stock_fev + num_remove"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "结果相等，数据一致性过关！"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 4. 源码及GitHub地址"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "ename": "SyntaxError",
     "evalue": "invalid character in identifier (<ipython-input-26-db6c9c9fe744>, line 1)",
     "output_type": "error",
     "traceback": [
      "\u001b[1;36m  File \u001b[1;32m\"<ipython-input-26-db6c9c9fe744>\"\u001b[1;36m, line \u001b[1;32m1\u001b[0m\n\u001b[1;33m    这一期为大家分享了一个简单的pandas检验数据一致性的模型，模型还是非常初级阶段，功能非常简单，但是基础的搭建流程想必大家已经熟悉了，接下来\u001b[0m\n\u001b[1;37m                                                                          ^\u001b[0m\n\u001b[1;31mSyntaxError\u001b[0m\u001b[1;31m:\u001b[0m invalid character in identifier\n"
     ]
    }
   ],
   "source": [
    "这一期为大家分享了一个简单的pandas检验数据一致性的模型，模型还是非常初级阶段，功能非常简单，但是基础的搭建流程想必大家已经熟悉了，接下来\n",
    "小伙伴们可以根据业务需求搭建自己的模型啦，只要你每天和Excel打交道，总有一款模型适合你\n",
    "\n",
    "我把这一期的ipynb文件和py文件放到了Github上，大家如果想要下载可以点击下面的链接：\n",
    " - Github仓库地址： [https://github.com/yaozeliang/pandas_share](https://github.com/yaozeliang/pandas_share/tree/master/Pandas%E4%B9%8B%E6%97%85_04%20pandas%E8%B6%85%E5%AE%9E%E7%94%A8%E6%8A%80%E5%B7%A7)\n",
    "\n",
    "\n",
    "希望大家能够继续支持我，完结，撒花"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
